package com.demo.api.service.dept.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.demo.api.cache.DeptCache;
import com.demo.api.interceptor.user.AuthUserInfo;
import com.demo.api.interceptor.user.UserInfo;
import com.demo.api.service.dept.IDeptService;
import com.demo.api.vo.dept.DeptVo;
import com.demo.client.mapper.user.*;
import com.demo.client.model.user.*;
import com.demo.core.enums.OftenEnum;
import com.demo.core.enums.RedisCacheEnum;
import com.demo.core.redis.RedisCache;
import com.demo.core.redis.RedisTableCache;
import com.demo.core.utils.StringUtils;
import com.demo.core.verification.ValidatorTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Tan-Bowen
 * @version 1.0
 * @description TODO
 * @date 2021/8/24 16:53
 */
@Slf4j
@Service
public class DeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements IDeptService {

    @Resource
    private SysDeptMapper deptMapper;

    @Resource
    private RedisTableCache redisTableCache;

    @Resource
    private RedisCache redisCache;

    @Resource
    private DeptCache deptCache;

    @Resource
    private SysUserRoleMapper userRoleMapper;

    @Resource
    private SysRoleMenuMapper roleMenuMapper;

    @Resource
    private SysUserMapper userMapper;

    @Resource
    private SysRoleMapper roleMapper;

    @Override
    public IPage<DeptVo.PageList> deptPage(Page<SysDept> page, DeptVo.Select select) {
        LambdaQueryWrapper<SysDept> query = new LambdaQueryWrapper<>();
        UserInfo userInfo = AuthUserInfo.getUser();
        query.eq(select.getPid() != null, SysDept::getPid, select.getPid());
        query.eq(select.getState() != null, SysDept::getState, select.getState());
        // 只能读取当前和子级的部门信息
        query.in(!userInfo.getDeptIds().isEmpty(), SysDept::getId, userInfo.getDeptIds());
        query.like(StringUtils.isNotBlank(select.getName()), SysDept::getName, select.getName());
        IPage<DeptVo.PageList> depts = deptMapper.selectPage(page, query).convert(dept -> BeanUtil.copyProperties(dept, DeptVo.PageList.class));
        depts.getRecords().forEach(e -> {
            SysUser user = redisTableCache.get(SysUser.class, e.getCreateUser());
            if (user != null) {
                e.setCreateName(user.getUserName());
            }
        });
        return depts;
    }

    @Override
    public void create(DeptVo.Create create) {
        UserInfo user = AuthUserInfo.getUser();
        create.setCreateUser(user.getUserId());
        SysDept dept = BeanUtil.copyProperties(create, SysDept.class);
        ValidatorTools.checkSqlSuccess(deptMapper.insert(dept), "新增机构失败");
        deptCache.sendRefreshEvent();
    }

    @Override
    public void update(DeptVo.Update update) {
        SysDept dept = BeanUtil.copyProperties(update, SysDept.class);
        ValidatorTools.checkSqlSuccess(deptMapper.updateById(dept), "编辑机构失败");
        redisTableCache.remove(SysDept.class, update.getId());
        deptCache.sendRefreshEvent();
    }

    public List<DeptVo.PageList> getUserDept() {
        List<Long> deptIds = AuthUserInfo.getDeptIds();
        LambdaQueryWrapper<SysDept> query = new LambdaQueryWrapper<>();
        query.eq(SysDept::getState, OftenEnum.EnableState.ENABLE.code());
        query.in(!deptIds.isEmpty(), SysDept::getId, deptIds);
        query.orderByAsc(SysDept::getId);
        return deptMapper.selectList(query)
                .stream()
                .map(e -> BeanUtil.copyProperties(e, DeptVo.PageList.class))
                .collect(Collectors.toList());

    }


    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void deleteDept(Long deptId) {
        SysDept dept = redisTableCache.get(SysDept.class, deptId);
        ValidatorTools.commonThrow(dept == null, "部门不存在");
        List<Long> deptIds = deptCache.getChildren(deptId);
        deptIds.add(deptId);
        //1. 获取到所有这个部门的用户
        List<Long> userIds = userMapper.selectList(new LambdaQueryWrapper<SysUser>().in(SysUser::getDeptId, deptIds)).stream().map(SysUser::getId).collect(Collectors.toList());
        //2. 获取到所有这个部门的角色
        List<Long> roleIds = roleMapper.selectList(new LambdaQueryWrapper<SysRole>().in(SysRole::getDeptId, deptIds)).stream().map(SysRole::getId).collect(Collectors.toList());
        //3.删除用户 和用户角色
        int count = 0;
        if (!userIds.isEmpty()) {
            ValidatorTools.checkSqlSuccess(userMapper.delete(new LambdaQueryWrapper<SysUser>().in(SysUser::getId, userIds)), "删除部门失败");
            userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getUserId, userIds));
            userIds.forEach(userId -> {
                redisTableCache.remove(SysDept.class, userId);
                redisCache.del(RedisCacheEnum.USER_ROLE.createKey(userId));
            });
        }
        if (!roleIds.isEmpty()) {
            roleMapper.delete(new LambdaQueryWrapper<SysRole>().in(SysRole::getDeptId, roleIds));
            roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().in(SysRoleMenu::getRoleId, roleIds));
            roleIds.forEach(roleId -> {
                redisTableCache.remove(SysRole.class, roleId);
                redisCache.del(RedisCacheEnum.ROLE_MENU.createKey(roleId));
            });
        }
        ValidatorTools.checkSqlSuccess(deptMapper.deleteBatchIds(deptIds),"删除部门失败");
        redisTableCache.remove(SysDept.class,deptId);
        deptCache.sendRefreshEvent();
    }
}
